package tech.yixiyun.framework.kuafu.controller.request.param;

import tech.yixiyun.framework.kuafu.bean.BeanContext;
import tech.yixiyun.framework.kuafu.bean.annotation.Priority;
import tech.yixiyun.framework.kuafu.controller.annotation.ContentType;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

public class ParamValueResolverContext {
    /**
     * 哪种contextType，由那个解析器处理
     */
    private static final ConcurrentHashMap<String, Class<? extends IRequestParamResolver>> RESOLVER_MAP = new ConcurrentHashMap<>();

    private static final List<Class<? extends IRequestParamResolver>> resolverClasses = new ArrayList<>();

    private static final ReentrantLock lock = new ReentrantLock();

    /**
     * 注册参数值解析器
     * @param resolverClass
     */
    public static void register(Class<? extends IRequestParamResolver> resolverClass) {
        if (resolverClasses.contains(resolverClass)) {
            return;
        }
        resolverClasses.add(resolverClass);
        calTypeMap();


    }

    /**
     * 生成各种类的处理类映射
     */
    private static void calTypeMap() {
        resolverClasses.sort((a, b) -> {
            double aPriority = 0;
            double bPriority = 0;
            Priority priority = a.getDeclaredAnnotation(Priority.class);
            if (priority != null) {
                aPriority = priority.value();
            }
            priority = b.getDeclaredAnnotation(Priority.class);
            if (priority != null) {
                bPriority = priority.value();
            }
            return aPriority == bPriority ? 0 : aPriority > bPriority ? 1 : -1;
        });
        /*
        优先级低的会被高的覆盖
         */
        resolverClasses.forEach(item -> {
            ContentType contentType = (ContentType) item.getDeclaredAnnotation(ContentType.class);
            String[] types = contentType.value();
            for (String type : types) {
                RESOLVER_MAP.put(type, item);
            }
        });
    }


    /**
     * 注销某个contentType的参数值解析器，该方法只由框架在热加载期间调用，切勿在线上生产环境调用。
     * @param clazz
     */
    public static void unregister(Class<? extends IRequestParamResolver> clazz) {
        resolverClasses.remove(clazz);

        RESOLVER_MAP.clear();
        calTypeMap();
    }

    /**
     * 获取参数解析器
     * @param contentType
     * @return
     */
    public static IRequestParamResolver getResolver(String contentType) {
        if (contentType == null) {
            contentType = "";
        }

        Class<? extends IRequestParamResolver> clazz = RESOLVER_MAP.get(contentType.trim().toLowerCase());
        if (clazz == null) {
            return null;
        }
        return BeanContext.getBean(clazz);
    }


}
